package com.gitee.liuzhi.demo.stream;

import com.gitee.liuzhi.common.model.Student;
import com.google.common.collect.Lists;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by 2024/8/2/0002
 *
 * @author LiuZhi
 * @version V1.0
 * @description: Stream API
 * <p>
 * Java 8中的集合支持一个新的stream方法，它会返回一个流java.util.stream.Stream
 * <p>
 * Stream 是什么：从支持数据处理操作的源生成的元素序列
 * 1. 元素序列：就像集合一样，流也提供了一个接口，可以访问特定元素类型的一组有序值
 * 因为集合是数据结构，所以它的主要目的是以特定的时间/空间复杂度存储和访问元素（如ArrayList 与 LinkedList）。
 * 但流的目的在于表达计算，比如你前面见到的filter、sorted和map。集合讲的是数据，流讲的是计算
 * 2. 源：流会使用一个提供数据的源，如集合、数组或输入/输出资源
 * 请注意，从有序集合生成流时会保留原有的顺序。由列表生成的流，其元素顺序与列表一致
 * 3. 数据处理操作：流的数据处理功能支持类似于数据库的操作，以及函数式编程语言中的常用操作
 * 如filter、map、reduce、find、match、sort等。流操作可以顺序执行，也可并行执行
 * <p>
 * Stream 特点
 * 1. 流水线：很多流操作本身会返回一个流，这样多个操作就可以链接起来，形成一个大的流水线。
 * 这让我们下一章中的一些优化成为可能，如延迟和短路
 * 2. 内部迭代：与使用迭代器显式迭代的集合不同，流的迭代操作是在背后进行的
 * 3. 流只能遍历一次：（遍历完后流已经被消费，只能从原始数据源处重新获得一个流）
 * <p>
 * Stream API 优点
 * 1. 声明性：更简洁、更易读
 * 代码是以声明性方式写的：说明想要完成什么，而不是说明如何实现
 * 2. 可复合：更灵活
 * 把几个基础操作链接起来：表达复杂的数据处理流水线，组合filter、sorted、collect等
 * 3. 可并行：性能更好
 * 并行处理流
 */
public class StreamDemo {

    private static final List<Student> STUDENT_LIST = Lists.newArrayList(
            new Student(1, "111", 11),
            new Student(2, "222", 22),
            new Student(3, "333", 33)
    );

    public static void main(String[] args) {

    }

    /**
     * 使用流
     * <p>
     * 流的使用包括三部
     * 1. 一个数据源（如集合）来执行一个查询
     * 2. 一个中间操作链，形成一条流的流水线
     * 3. 一个终端操作，执行流水线，并能生成结果
     */
    private static void testUseStream() {
        // 谓词筛选 filter

        // 筛选各异的元素 distinct （根据元素的hashCode和equals方法实现）

        // 截短流 limit

        // 跳过元素 skip

        // 映射 map flatMap
    }

    private static void testStream() {
        // STUDENT_LIST就是一个数据源
        List<String> collect = STUDENT_LIST
                // 得到一个流，由数据源给流提供一个元素序列
                .stream()
                // 从流中排除某些元素
                .filter(x -> x.getId() > 0)
                .sorted(Comparator.comparing(Student::getId))
                // 将元素转换成其他形式或提取信息
                .map(Student::getName)
                // 截断流，使其元素不超过给定数量
                .limit(1)
                // 将流转换为其他形式
                // collect操作开始处理流水线，并返回结果，在这之前不会产生任何实际结果，链中的方法调用都在排队等待
                .collect(Collectors.toList());
    }

}
